package com.cookor.poi.modules.weixin.account;

import com.cookor.poi.common.utils.SpringContextHolder;
import com.cookor.poi.modules.weixin.entity.TWeixinConfig;

import com.cookor.poi.modules.weixin.service.TWeixinConfigService;
import com.cookor.poi.utils.CacheFactory;
import com.cookor.poi.utils.HttpUtils;
import com.google.common.collect.Maps;

import com.xiaoleilu.hutool.http.HttpUtil;
import com.xiaoleilu.hutool.json.JSONObject;
import com.xiaoleilu.hutool.json.JSONUtil;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

public class PlatformAccount extends Account {

	private final static Logger logger = Logger.getLogger(PlatformAccount.class);

	public PlatformAccount(TWeixinConfig weixinConfig) {
		super(weixinConfig);
		this.weixinConfig = weixinConfig;
	}

	// 获取第三方平台component_access_token
	private static final String WEIXINPLATFORM_API_COMPONENT_TOKEN = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
	// 获取预授权码pre_auth_code
	private static final String WEIXINPLATFORM_API_CREATE_PREAUTHCODE = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=%s";
	// 使用授权码换取公众号的接口调用凭据和授权信息
	private static final String WEIXINPLATFORM_API_QUERY_AUTH_INFO = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=%s";
	// 获取（刷新）授权公众号的接口调用凭据（令牌）
	private static final String WEIXINPLATFORM_API_AUTHORIZER_TOKEN = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=%s";
	// 获取授权方的公众号帐号基本信息
	private static final String WEIXINPLATFORM_API_GET_AUTHORIZER_INFO = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=%s";
	// 获取授权方的选项设置信息
	private static final String WEIXINPLATFORM_API_GET_AUTHORIZER_OPTION = "https://api.weixin.qq.com/cgi-bin/component/ api_get_authorizer_option?component_access_token=%s";
	// 请求CODE
	private static final String WEIXINPLATFORM_API_OAUTH_CODE = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&component_appid=%s#wechat_redirect";
	// 通过code换取access_token
	private static final String WEIXINPLATFORM_API_OAUTH_INFO = "https://api.weixin.qq.com/sns/oauth2/component/access_token?appid=%s&component_appid=%s&code=%s&grant_type=authorization_code&component_access_token=%s";
	// 授权登陆地址
	private static final String WEIXINPLATFORM_API_LOGIN = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s";

	public JSONObject getAuthorizerOption(String optionname) throws WeixinTicketNotFoundException {
		String component_accesstoken = getComponentAccesstoken();
		Map<String, Object> params = Maps.newConcurrentMap();
		params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
		params.put("authorizer_appid", weixinConfig.getAppid());
		params.put("option_name", optionname);
		String url = String.format(WEIXINPLATFORM_API_GET_AUTHORIZER_OPTION,
				component_accesstoken);
		return httpPost(url, JSONUtil.toJsonStr(params));
	}

	public static JSONObject getAccountInfo(String appid) throws WeixinTicketNotFoundException {
		Map<String, Object> params = Maps.newConcurrentMap();
		params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
		params.put("authorizer_appid", appid);
		String url = String.format(WEIXINPLATFORM_API_GET_AUTHORIZER_INFO,getComponentAccesstoken());
		JSONObject authorizer_info = httpPost(url, JSONUtil.toJsonStr(params));
		return authorizer_info;
		/*String component_accesstoken = getComponentAccesstoken();
		appid = StringUtils.isBlank(appid) ? weixinConfig.getAppid() : appid;
		Map<String, Object> params = Maps.newConcurrentMap();
		params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
		params.put("authorizer_appid", appid);
		String url = String.format(WEIXINPLATFORM_API_GET_AUTHORIZER_INFO,
				component_accesstoken);
		return httpPost(url, JSONUtil.toJsonStr(params));*/
	}



	public static String getTicket() {
//		String ticket = (String) CacheFactory.get("account:ticket:"
//				+ ThirdPlatform.COMPONENTAPPID);

		String ticket = HttpUtil.get("http://zx.nthink.cn/wx/phy/test/getTicket").replace("\n","");
		System.out.println(ticket);
//		ticket = "ticket@@@bpeqYi3Vc8GBlnc75SCRWaCuJceb23NpNx696LwqRBn3zDA8siiXhv2TFG2IGWHH_9uaN8SRClvgCmiDgH-Lgw";
//		if(StringUtils.isBlank(ticket)){
//			WeixinThirdplatService weixinThirdplatService = SpringContextHolder
//					.getBean(WeixinThirdplatService.class);
//			List<WeixinThirdplat> list = weixinThirdplatService.findList(new WeixinThirdplat());
//			if(list.size()>0){
//				return list.get(0).getTicket();
//			}
//		}
		return ticket;
	}

	public static void setTicket(String componentAppid, String ticket) {
		String cachename = "account:ticket:" + componentAppid;
		CacheFactory.put(cachename, ticket);
//		WeixinThirdplatService weixinThirdplatService = SpringContextHolder
//				.getBean(WeixinThirdplatService.class);
//		WeixinThirdplat weixinThirdplat = new WeixinThirdplat();
//		List<WeixinThirdplat> list = weixinThirdplatService.findList(weixinThirdplat);
//		if(list.size()>0){
//			weixinThirdplat = list.get(0);
//			weixinThirdplat.setTicket(ticket);
//			weixinThirdplatService.save(weixinThirdplat);
//		}
	}

	public static JSONObject getAuthInfo(String code) throws WeixinTicketNotFoundException {
		String component_accesstoken = getComponentAccesstoken();
		Map<String, Object> params = Maps.newConcurrentMap();
		params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
		params.put("authorization_code", code);
		String url = String.format(WEIXINPLATFORM_API_QUERY_AUTH_INFO,
				component_accesstoken);
		System.out.println("getAuthInfo:" + url);
		return httpPost(url, JSONUtil.toJsonStr(params));
	}

	public static TWeixinConfig getAppidByAuthCode(String code, String officeId)throws WeixinTicketNotFoundException {
		JSONObject jsonObject = getAuthInfo(code);
		JSONObject authorization_info = jsonObject.getJSONObject("authorization_info");
		String appid = authorization_info.getStr("authorizer_appid");
		String authorizer_access_token = authorization_info.getStr("authorizer_access_token");
		String expires_in = authorization_info.getStr("expires_in");
		String authorizer_refresh_token = authorization_info.getStr("authorizer_refresh_token");
		/*
		Map<String,Object> params = Maps.newConcurrentMap();
		params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
		params.put("authorizer_appid", appid);
		String url = String.format(WEIXINPLATFORM_API_GET_AUTHORIZER_INFO,getComponentAccesstoken());*/
		JSONObject authorizer_info = getAccountInfo(appid);

		//保存公众号信息
		TWeixinConfigService weixinConfigService = SpringContextHolder
				.getBean(TWeixinConfigService.class);
		TWeixinConfig wc = weixinConfigService.save(officeId,authorizer_refresh_token,authorizer_info);
		//保存公众号信息
		setAuthRefreshToken(appid,authorizer_refresh_token);//缓存凭据刷新令牌
		if(StringUtils.isNoneBlank(authorizer_access_token)){//缓存公众号token
			saveCacheAccessToken(appid,authorizer_access_token, Integer.parseInt(expires_in));
		}
		return wc;
	}



	public static String getComponentAccesstoken() throws WeixinTicketNotFoundException {

		String token = HttpUtil.get("http://zx.nthink.cn/wx/phy/test/getToken?tenantId=5").replace("\n","");
		System.out.println(token);
		return token;

//		String cachename = "account:component:assesstoken:"
//				+ ThirdPlatform.COMPONENTAPPID;
//		Map<String, String> map = (Map<String, String>) CacheFactory
//				.get(cachename);
//		if (!isUseCache(map)) {
//			String ticket = getTicket();
//			if (StringUtils.isBlank(ticket)) {
//				String msg = "缺少接入平台关键数据，等待微信开放平台推送数据，请十分钟后再试";
//				throw new WeixinTicketNotFoundException(msg);
//			}
// 			Map<String, Object> params = Maps.newConcurrentMap();
//			params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
//			params.put("component_appsecret", ThirdPlatform.COMPONENTAPPSECRET);
//			params.put("component_verify_ticket", ticket);
//			JSONObject jsonObject = httpPost(
//					WEIXINPLATFORM_API_COMPONENT_TOKEN, JSONUtil.toJsonStr(params));
//			String component_access_token = jsonObject
//					.getStr("component_access_token");
//			int expires_in = Integer.valueOf(jsonObject.getStr("expires_in"));
//			if (map == null) {
//				map = Maps.newConcurrentMap();
//			}
//			map.put("value", component_access_token);
//			long TIMESTAMP = System.currentTimeMillis() / 1000;
//			map.put("expire", "" + (TIMESTAMP + expires_in));
//			CacheFactory.put(cachename, map);
//		}
//		return map.get("value");
	}

	public String getAuthRefreshToken() {
		String authRefreshToken = weixinConfig.getAuthRefreshToken();
		if (StringUtils.isBlank(authRefreshToken)) {
			String cachename = "account:auth:refreshtoken:"
					+ weixinConfig.getAppid();
			authRefreshToken = (String) CacheFactory.get(cachename);
		}
		return authRefreshToken;
	}
	public static void setAuthRefreshToken(String appid, String authRefreshToken){
		String cachename = "account:auth:refreshtoken:"
			+ appid;
		CacheFactory.put(cachename, authRefreshToken);
		TWeixinConfigService weixinConfigService = SpringContextHolder
				.getBean(TWeixinConfigService.class);
		weixinConfigService.updateAuthRefreshToken(appid,
				authRefreshToken);
	}



	public void setAuthRefreshToken(String authRefreshToken) {
		setAuthRefreshToken(weixinConfig.getAppid(),authRefreshToken);

	}
	public static  void saveCacheAccessToken(String appid, String authorizer_access_token, int expires_in){
		Map<String, String> map = Maps.newConcurrentMap();
		String cachename = "account:auth:accesstoken:"+ appid;
		long TIMESTAMP = System.currentTimeMillis() / 1000;
		map.put("value", authorizer_access_token);
		map.put("expire", "" + (TIMESTAMP + expires_in));
		CacheFactory.put(cachename, map);
	}
	public String getAccessToken() throws WeixinTicketNotFoundException {
		String cachename = "account:auth:accesstoken:"
				+ weixinConfig.getAppid();
		Map<String, String> map = (Map<String, String>) CacheFactory
				.get(cachename);
		if (isUseCache(map)) {
			String component_accesstoken = getComponentAccesstoken();
			String refreshtoken = getAuthRefreshToken();
			Map<String, Object> params = Maps.newConcurrentMap();
			params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
			params.put("authorizer_appid", weixinConfig.getAppid());
			params.put("authorizer_refresh_token", refreshtoken);
			String url = String.format(WEIXINPLATFORM_API_AUTHORIZER_TOKEN,
					component_accesstoken);
			System.out.println("url:"+url);
			System.out.println("params:"+ JSONUtil.toJsonStr(params));
			JSONObject jsonObject = httpPost(url, JSONUtil.toJsonStr(params));
			String authorizer_refresh_token = jsonObject
					.getStr("authorizer_refresh_token");
			String authorizer_access_token = jsonObject.getStr("authorizer_access_token");
			if (authorizer_refresh_token != getAuthRefreshToken()) {
				setAuthRefreshToken(authorizer_refresh_token);
			}
			int expires_in = Integer.valueOf(jsonObject.getStr("expires_in"));
			saveCacheAccessToken(weixinConfig.getAppid(),authorizer_access_token,expires_in);
			return authorizer_access_token;
		}
		return map.get("value");
	}

	public static String getPreauthCode() throws WeixinTicketNotFoundException {
		String cachename = "preauthcode:" + ThirdPlatform.COMPONENTAPPID;
		Map<String, String> map = (Map<String, String>) CacheFactory
				.get(cachename);
		long TIMESTAMP = System.currentTimeMillis() / 1000;
		if (isUseCache(map)) {
			String component_accesstoken = getComponentAccesstoken();
			String url = String.format(WEIXINPLATFORM_API_CREATE_PREAUTHCODE,
					component_accesstoken);

			Map<String, Object> params = Maps.newConcurrentMap();
			params.put("component_appid", ThirdPlatform.COMPONENTAPPID);
			JSONObject jsonObject = httpPost(url, JSONUtil.toJsonStr(params));
			String pre_auth_code = jsonObject.getStr("pre_auth_code");
			int expires_in = Integer.valueOf(jsonObject.getStr("expires_in"));
			if(map==null){
				map = Maps.newConcurrentMap();
			}
			map.put("value", pre_auth_code);
			map.put("expire", "" + (TIMESTAMP + expires_in));
			CacheFactory.put(cachename, map);
		}
		return map.get("value");
	}

	public static String getAuthLoginUrl(String callbackurl) throws WeixinTicketNotFoundException {
		String preauthcode = getPreauthCode();
		String redirect_uri;
		try {
			redirect_uri = URLEncoder.encode(callbackurl, "utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage());
			return "";
		}
		return String.format(WEIXINPLATFORM_API_LOGIN,
				ThirdPlatform.COMPONENTAPPID, preauthcode, redirect_uri);
	}

	public JSONObject getOauthInfo(String code) throws WeixinTicketNotFoundException {
		String url = String.format(WEIXINPLATFORM_API_OAUTH_INFO,
				weixinConfig.getAppid(), ThirdPlatform.COMPONENTAPPID, code,
				getComponentAccesstoken());
		return httpGet(url);
	}

	public String getOauthCodeUrl(String callbackurl, String state, String scope)
			throws UnsupportedEncodingException {
		if (StringUtils.isBlank(scope)) {
			scope = "snsapi_base";
		}
		String redirect_uri = URLEncoder.encode(callbackurl, "utf-8");
		return String.format(WEIXINPLATFORM_API_OAUTH_CODE,
				weixinConfig.getAppid(),
				redirect_uri, scope, state, ThirdPlatform.COMPONENTAPPID);
	}

//	public static void openPlatformTestCase(HttpServletRequest request,
//                                            HttpServletResponse response) throws AesException,
//            DocumentException, IOException, WeixinTicketNotFoundException {
//		String nonce = request.getParameter("nonce");
//		String timestamp = request.getParameter("timestamp");
//		String msgSignature = request.getParameter("msg_signature");
//
//		String xml = RequestUtils.getRequestBody(request);
//		System.out.println("xml:" + xml);
//		WXBizMsgCrypt pc = new WXBizMsgCrypt(ThirdPlatform.TOKEN,
//				ThirdPlatform.ENCODINGAESKEY, ThirdPlatform.COMPONENTAPPID);
//		String result = pc.decryptMsg(msgSignature, timestamp, nonce, xml);
//		System.out.println("result:" + result);
//		Map<String, String> messageMap = XmlUtils.xmlToMap(result);
//		System.out.println(messageMap);
//		long TIMESTAMP = System.currentTimeMillis() / 1000;
//		Map<String, String> responseMap = Maps.newConcurrentMap();
//		String from = messageMap.get("FromUserName");
//		String to = messageMap.get("ToUserName");
//		String content = messageMap.get("Content");
//		String msgId = messageMap.get("MsgId");
//		String msgType = messageMap.get("MsgType");
//		responseMap.put("ToUserName", from);
//		responseMap.put("FromUserName", to);
//		responseMap.put("CreateTime", "" + TIMESTAMP);
//		responseMap.put("MsgId", "" + msgId);
//		responseMap.put("MsgType", "text");
//		if ("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)) {
//			responseMap.put("Content", "TESTCOMPONENT_MSG_TYPE_TEXT_callback");
//		} else if ("event".equals(msgType)) {
//			String event = messageMap.get("Event");
//			responseMap.put("Content", event + "from_callback");
//		} else {
//			System.out.println("+++++++++++");
//			System.out.println("msgType:" + msgType);
//			System.out.println("index:" + content.indexOf("QUERY_AUTH_CODE"));
//			System.out.println("+++++++++++");
//
//			if ("text".equals(msgType)
//					&& content.indexOf("QUERY_AUTH_CODE") != -1) {
//
//				String authcode = content.split(":")[1];
//				JSONObject jsonObject = getAuthInfo(authcode);
//				String authorizer_access_token = JSONUtil.parseObj(
//						jsonObject.getStr("authorization_info")).getStr(
//						"authorizer_access_token");
//				Map<String, Object> paramsMap = Maps.newConcurrentMap();
//				Map<String, Object> paramsMap2 = Maps.newConcurrentMap();
//				paramsMap.put("touser", from);
//				paramsMap.put("msgtype", "text");
//				paramsMap2.put("content", authcode + "_from_api");
//				paramsMap.put("text", paramsMap2);
//				output(response, "");
//				sendCustom(authorizer_access_token, paramsMap);
//				return;
//			}
//		}
//		String replyMsg = MessageUtil.mapTotextMessage(responseMap);
//		System.out.println("replyMsg:" + replyMsg);
//		String mingwen = pc.encryptMsg(replyMsg, timestamp, nonce);
//		System.out.println("mingwen:" + mingwen);
//		output(response, mingwen);
//	}

	public static void output(HttpServletResponse response, String returnvaleue) {
		try {
			PrintWriter pw = response.getWriter();
			pw.write(returnvaleue);
			pw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
